﻿using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;

using System.Linq;
using SlamCms.SharePoint.Core;
using System.Text;
using SlamCms.Data;
using System.Collections.Generic;
using Microsoft.SharePoint;
using System.Web;

namespace SlamCms.SharePoint.Publishing.WebParts
{



	public partial class AddPublisherDetail : UserControl
	{

	   //private ControlMode _mode;

		public ControlMode Mode { get; set; }

		public int UserID { get; set; }

		private string _roleKeywords = "Publishers;Editors";

		public string RoleKeywords
		{
			get
			{
				return _roleKeywords;
			}
			set
			{
				_roleKeywords = value;
			}
		}


		protected void Page_Load(object sender, EventArgs e)
		{
			Page.ClientScript.RegisterClientScriptInclude("jquery", ResolveUrl("~/_layouts/inc/jquery-1.6.2.min.js"));
			Page.ClientScript.RegisterClientScriptInclude("jquery.ui.core", ResolveUrl("~/_layouts/inc/jquery.ui.core.js"));
			Page.ClientScript.RegisterClientScriptInclude("jquery.ui.widget", ResolveUrl("~/_layouts/inc/jquery.ui.widget.js"));
			Page.ClientScript.RegisterClientScriptInclude("jquery.ui.position", ResolveUrl("~/_layouts/inc/jquery.ui.position.js"));
			Page.ClientScript.RegisterClientScriptInclude("jquery.ui.mouse", ResolveUrl("~/_layouts/inc/jquery.ui.mouse.js"));
			Page.ClientScript.RegisterClientScriptInclude("jquery.ui.autocomplete", ResolveUrl("~/_layouts/inc/jquery.ui.autocomplete.js"));
			Page.ClientScript.RegisterClientScriptInclude("jquery.cookie", ResolveUrl("~/_layouts/inc/jquery.cookie.js"));

			Page.ClientScript.RegisterClientScriptInclude("chosen", ResolveUrl("~/_layouts/inc/chosen.jquery.js"));


			AddCssInclude("~/_layouts/1033/STYLES/SlamCms.Tagging.TagManager.css");
			AddCssInclude("~/_layouts/1033/STYLES/chosen.css");

			int[] selectedRoles = new int[] {};
			string[] selectedTopics = new string[] {};

			if (!Page.IsPostBack)
			{
				if (Mode == ControlMode.Edit)
				{
					var user = SlamCmsContext.Data.Users.Where(u => u.UserId.Equals(this.UserID)).FirstOrDefault();
					if (user != null)
					{
						this.txtUser.Value = user.Name;
                        this.hdnSelectedUser.Value = this.UserID.ToString();
						//StringBuilder builder = new StringBuilder("");
						//builder.AppendLine("Roles IDs: " + String.Join(";", GetUserRoles(user).Select(s => s.ToString()).ToArray()));
						//builder.AppendLine("TopicsIds: "+ String.Join(";",GetUserTopics(user)));
						//txtDisplay.Text = builder.ToString();
					   
					   //LoadSelectRoles(GetUserRoles(user));
					   //LoadSelectTopics(GetUserTopics(user));

					   selectedRoles = GetUserRoles(user);
					   selectedTopics = GetUserTopics(user);
					   // txtDisplay.Text = String.Join(";", GetUserRoles(user).Select(s => s.ToString()).ToArray());
					}
				}
				if (Mode == ControlMode.New)
				{
					LoadSelectUsers();
				}

				LoadSelectRoles(selectedRoles);
				LoadSelectTopics(selectedTopics);

				ControlsDisplay();
			}
		}


		private void ControlsDisplay()
		{
			HideAll();
			switch (Mode)
			{ 
				case(ControlMode.New):
					//txtUser.Disabled = false;
					selectUsers.Visible = true;
					btnAddUser.Visible = true;
					btnCancel.Visible = true;
					break;
				case(ControlMode.Edit):
					txtUser.Visible = true;
					txtUser.Disabled = true;
					btnSaveUser.Visible = true;
					btnDelete.Visible = true;
					btnCancel.Visible = true;
					break;
				default:
					break;
			
			}

			
		}

		private void HideAll()
		{
            //this.txtError.Visible = false;
			selectUsers.Visible = false;
			txtUser.Visible = false;
			btnAddUser.Visible = false;
			btnCancel.Visible = false;
			btnDelete.Visible = false;
			btnSaveUser.Visible = false;

		}

		private int[] GetUserRoles(SlamCms.Data.User user)
		{ 
			string[] keys = this.RoleKeywords.Split(';');

             //if(keys.Contains("Site Collection Administrator (KC)"))
             //    return new int[]{0};

			return user.Groups.Where(g => keys.Any(k => !String.IsNullOrEmpty(k) && g.Name.Contains(k)) && g.Sites != null).Select(i => i.GroupId).ToArray();
					  
			//return ids;
		}

		private string[] GetUserTopics(SlamCms.Data.User user)
		{
			return user.OwnedTags.Select(i =>  i.TagId).ToArray();
		}

		private void LoadSelectUsers()
		{
			var users = SlamCmsContext.Data.Users.ToDictionary(u => u.UserId, u => u.Name+ "("+u.UserName+")");

			foreach (KeyValuePair<int, string> u in users)
			{
				this.selectUsers.Items.Add(new ListItem(u.Value, u.Key.ToString()));
			}


		}

		private void LoadSelectRoles(int[] selectedRolesID)
		{
			string[] keys = this.RoleKeywords.Split(';');
           // List<string> addedRoles = new List<string>();
            List<ListItem> addedGroups = new List<ListItem>();

			var groups = (from g in SlamCmsContext.Data.Groups.Where(g => keys.Any(k => !String.IsNullOrEmpty(k) && g.Name.Contains(k)) && g.Sites != null && g.SiteCollectionGroupId != 0)
						  select g).ToList();
			if (groups != null)
			{
				foreach (SlamCms.Data.Group g in groups)
				{
					ListItem selectItem = null;
					bool selected = selectedRolesID.Contains(g.GroupId);
                    if (selected)
                    {
                        int sit = g.Sites.Count;
                    }
                    if (g.Sites.Count > 0)
                    {
                        //foreach (SlamCms.Data.Site s in g.Sites)
                        //{
                        //SlamCms.Data.Zone z = s.Zones.FirstOrDefault();
                        SlamCms.Data.Zone z = g.Sites.FirstOrDefault().Zones.FirstOrDefault();
                        string text = (z != null ? (z.Title + ":") : String.Empty) + g.Name;
                        string value = g.GroupId.ToString();
                        if (addedGroups.Where(o => o.Value.Equals(value)).FirstOrDefault() == null)
                        {
                            selectItem = new ListItem(text, value);
                            selectItem.Selected = selected;

                            addedGroups.Add(selectItem);
                        }
                        //}
                    }
                    else
                    {
                        selectItem = new ListItem(g.Name, g.GroupId.ToString());
                        selectItem.Selected = selected;
                        addedGroups.Add(selectItem);
                    }
				}

                this.selectRoles.Items.AddRange(addedGroups.OrderBy(o => o.Text).ToArray());
			}

			//this.selectRoles.Items.Add(new ListItem("Construction Publishers"));
			//this.selectRoles.Items.Add(new ListItem("KC:Librarian Publishers"));
			//this.selectRoles.Items.Add(new ListItem("KC:Global News and Events Publishers"));
			//this.selectRoles.Items.Add(new ListItem("KC:Learning Resources Publishers"));
			//this.selectRoles.Items.Add(new ListItem("KC:HFHI Administration Publishers"));
			//this.selectRoles.Items.Add(new ListItem("National Service Publishers"));


		}


		private void LoadSelectTopics(string[] selectedTopicsID)
		{
			//var category = SlamCmsContext.Data.TagCategories.Where(cat => cat.Title.Equals("Topics")).FirstOrDefault();
			//var tagTree = SlamCmsContext.Data.GetTagTree().FilterTagCategories(new string[] { category.TagCategoryId });
           // var tagTree = SlamCmsContext.Data.GetTagTree();
           //var nodes = tagTree.FindNodes(n => !String.IsNullOrEmpty(n.Identifier));

            var nodes = SlamCmsContext.Data.Tags.Where(n => !String.IsNullOrEmpty(n.Identifier)).ToList();
            
			//var nodes = tagTree.FindNodes(n => !String.IsNullOrEmpty(n.Tag.TagId));
			Dictionary<string, string> topics = new Dictionary<string, string>();

			foreach (Tag n in nodes)
			{
				if (!topics.ContainsKey(n.TagId))
					topics.Add(n.TagId, String.IsNullOrEmpty(n.DisplayName) ? (n.DisplayName + " (" + n.Identifier+ ")") : n.Identifier);
			}

			////var tagTree = SlamCmsContext.Data.GetTagTree().FindNodes(n => n.IsTag() && n.BelongsToTagCategory(category.TagCategoryId)&& !String.IsNullOrEmpty(n.Identifier)).Take(10);
			////var topics = tagTree.ToDictionary(t => t.Identifier, t => t.Identifier);
			////var topics = tagTree.FindNodes(n => !String.IsNullOrEmpty(n.Identifier)).ToDictionary(t => t.Identifier, t => t.Identifier);

			foreach (KeyValuePair<string, string> t in topics)
			{
				ListItem selectItem = new ListItem(t.Value,t.Key);
				selectItem.Selected = selectedTopicsID.Contains(t.Key);
				this.selectTopics.Items.Add(selectItem);
			}


			//this.selectTopics.Items.Add(new ListItem("Advocacy", "advocacy") { Selected = true });
			//this.selectTopics.Items.Add(new ListItem("Advocacy Liaison", "advocacy-liaison"));
			//this.selectTopics.Items.Add(new ListItem("Congress", "congress") { Selected = true });
			//this.selectTopics.Items.Add(new ListItem("Appropriations", "appropriations"));
			//this.selectTopics.Items.Add(new ListItem("Congress Build America", "build-america"));
			//this.selectTopics.Items.Add(new ListItem("Foreign Aid Reform", "foreign-aid"));
			//this.selectTopics.Items.Add(new ListItem("Habitat on the Hill", "habitat-on-hill"));
			//this.selectTopics.Items.Add(new ListItem("Legislative Priorities", "legislative-priorities"));
			//this.selectTopics.Items.Add(new ListItem("Safe Act", "safe-act"));
			//this.selectTopics.Items.Add(new ListItem("Serve America Act", "serve-america"));
		}

		private void AddCssInclude(string url)
		{
			string include = String.Format("<link rel=\"stylesheet\" type=\"text/css\" href=\"{0}\" media=\"all\" />", ResolveUrl(url));
			if (!Page.Header.Controls.Cast<Control>().OfType<LiteralControl>().Any(c => c.Text == include))
			{
				Page.Header.Controls.Add(new LiteralControl(include));
			}
		}

		#region Events

		protected void AddUser_OnClick(object sender, EventArgs e)
		{
			//var user = SlamCmsContext.Entities.Users.Include("Groups").Include("Groups").Include("Groups.Sites").Include("Groups.Sites.SiteCollection").Include("Tags").ToList().Where(u => u.Name.ToUpper().Equals(this.hdnSelectedUser.Value.ToUpper()) || u.UserName.ToUpper().Equals(this.hdnSelectedUser.Value.ToUpper())).FirstOrDefault();

			var user = SlamCmsContext.Entities.Users.Include("Groups").Include("Groups.Sites").Include("Groups.Sites.SiteCollection").Include("Tags").ToList().Where(u => u.UserID.Equals(int.Parse(this.hdnSelectedUser.Value))).FirstOrDefault();

            try
            {

                AddUserAssociations(user);
                CloseModalWindow("1");
            }
            catch (Exception ex)
            {
                //this.txtError.Visible = true;
                //this.txtError.Text = ex.Message;
                this.ltError.Text = ex.Message;
                
            }

			
		}



		protected void btnSaveUser_Click(object sender, EventArgs e)
		{
            //var user = SlamCmsContext.Entities.Users.Include("Groups").Include("Groups.Sites").Include("Groups.Sites.SiteCollection").Include("Tags").ToList().Where(u => u.Name.ToUpper().Equals(this.hdnSelectedUser.Value.ToUpper()) || u.UserName.ToUpper().Equals(this.hdnSelectedUser.Value.ToUpper())).FirstOrDefault();

			var user = SlamCmsContext.Entities.Users.Include("Groups").Include("Groups.Sites").Include("Groups.Sites.SiteCollection").Include("Tags").ToList().Where(u => u.UserID.Equals(int.Parse(this.hdnSelectedUser.Value))).FirstOrDefault();

            //try
            //{
                UpdateUser(user);
                CloseModalWindow("1");
            //}
            //catch (Exception ex)
            //{
                //this.txtError.Text = ex.Message;
                //this.txtError.Visible = true;
                //this.ltError.Text = ex.Message;
            //}

			
		}


		protected void btnDelete_Click(object sender, EventArgs e)
		{
            //var user = SlamCmsContext.Entities.Users.Include("Groups").Include("Groups.Sites").Include("Groups.Sites.SiteCollection").Include("Tags").ToList().Where(u => u.Name.ToUpper().Equals(this.hdnSelectedUser.Value.ToUpper()) || u.UserName.ToUpper().Equals(this.hdnSelectedUser.Value.ToUpper())).FirstOrDefault();

			var user = SlamCmsContext.Entities.Users.Include("Groups").Include("Groups.Sites").Include("Groups.Sites.SiteCollection").Include("Tags").ToList().Where(u => u.UserID.Equals(int.Parse(this.hdnSelectedUser.Value))).FirstOrDefault();
            //try
            //{
                CleanUserAssociations(user);
                CloseModalWindow("1");
            //}
            //catch (Exception ex)
            //{
                //this.txtError.Text = ex.Message;
                //this.txtError.Visible = true;
            //    this.ltError.Text = ex.Message;
            //}
		}

		protected void btnCancel_Click(object sender, EventArgs e)
		{
			CloseModalWindow("0");
		}


		
		#endregion


		private void CloseModalWindow(string result)
		{
			this.Page.Response.Clear();
			this.Page.Response.Write(String.Format("<script type=\"text/javascript\">window.frameElement.commonModalDialogClose({0}, 1);</script>",result));
			this.Page.Response.End();
		}

		private void AddUserAssociations(SharePoint.Data.User user)
		{
			if (user != null)
			{
				string[] keys = this.RoleKeywords.Split(';');
				var existingGroups = user.Groups.ToList().Where(g => keys.Any(k => !String.IsNullOrEmpty(k) && g.Name.Contains(k)) && g.Sites != null);
                if (existingGroups.Count() > 0)
                {
                    throw new Exception("This user already exists and has roles assigned. Please update the existing user.");
                }
				
				var addGroups = GetGroups();
				foreach (SharePoint.Data.Group g in addGroups)
					user.Groups.Add(g);
				
				if(user.Tags.Count >0)
                    throw new Exception("This user already exists and has topics assigned. Please update the existing user.");
				foreach (SharePoint.Data.Tag t in GetTopics())
					user.Tags.Add(t);

				SlamCmsContext.Entities.SaveChanges();

				UpdateSharePointGroups(user, addGroups, true);

				SlamCmsContext.Data.Cache.InvalidateUsers();
				SlamCmsContext.Data.Cache.InvalidateCore();
				SlamCmsContext.Data.Cache.InvalidateTags();

			}
		}

		private void UpdateUser(SharePoint.Data.User user)
		{
			if (user != null)
			{
				UpdateUserGroups(user);
				UpdateUserTopics(user);

				SlamCmsContext.Data.Cache.InvalidateUsers();
				SlamCmsContext.Data.Cache.InvalidateCore();
				SlamCmsContext.Data.Cache.InvalidateTags();
			}
		}

		private void UpdateUserGroups(SharePoint.Data.User user)
		{
			string[] keys = this.RoleKeywords.Split(';');
			var existingGroups = user.Groups.ToList().Where(g => keys.Any(k => !String.IsNullOrEmpty(k) && g.Name.Contains(k)) && g.Sites != null);
			var updateGroups = GetGroups();
			
			List<SharePoint.Data.Group> toDelete = new List<SharePoint.Data.Group>();
			foreach (SharePoint.Data.Group g in existingGroups)
			{
				if (!updateGroups.Any(ug => ug.GroupID.Equals(g.GroupID)))
					toDelete.Add(g);
			}

			List<SharePoint.Data.Group> toAdd = new List<SharePoint.Data.Group>();
			foreach (SharePoint.Data.Group g in updateGroups)
			{
				if (!existingGroups.Any(eg => eg.GroupID.Equals(g.GroupID)))
					toAdd.Add(g);
			}

			// Adding and removing of the users
			foreach (SharePoint.Data.Group g in toDelete)
				user.Groups.Remove(g);

			foreach (SharePoint.Data.Group g in toAdd)
				user.Groups.Add(g);

			SlamCmsContext.Entities.SaveChanges();

			//Update Sharepoint Sites
			UpdateSharePointGroups(user, toDelete, false);
			UpdateSharePointGroups(user, toAdd, true);
		}

		private void UpdateUserTopics(SharePoint.Data.User user)
		{
			//string[] keys = this.RoleKeywords.Split(';');
			var existingTopics = user.Tags.ToList();
			var updateTopics = GetTopics();

			List<SharePoint.Data.Tag> toDelete = new List<SharePoint.Data.Tag>();
			foreach (SharePoint.Data.Tag t in existingTopics)
			{
				if (!updateTopics.Any(ut => ut.TagID.Equals(t.TagID)))
					toDelete.Add(t);
			}

			List<SharePoint.Data.Tag> toAdd = new List<SharePoint.Data.Tag>();
			foreach (SharePoint.Data.Tag t in updateTopics)
			{
				if (!existingTopics.Any(et => et.TagID.Equals(t.TagID)))
					toAdd.Add(t);
			}

			// Adding and removing
			foreach (SharePoint.Data.Tag t in toDelete)
				user.Tags.Remove(t);

			foreach (SharePoint.Data.Tag t in toAdd)
				user.Tags.Add(t);

			SlamCmsContext.Entities.SaveChanges();
		}

		//private void AddUserToSharePointGroups(SlamCms.Data.User user, List<SharePoint.Data.Group> groups)
		//{ 
		//    foreach(SharePoint.Data.Group g in groups)
		//    {
		//        foreach(SharePoint.Data.Site s in g.Sites)
		//        {
		//            using(var site = new SPSite(s.SiteCollection.SiteCollectionID))
		//            {
		//                using(var web = site.OpenWeb(site.ID))
		//                {
		//                    web.AllowUnsafeUpdates = true;
		//                    var spGroup = web.Groups[g.Name];
		//                    if(spGroup != null)
		//                    {
		//                        SPUser spUser = web.EnsureUser(String.Format("i:0#.w|{0}", user.UserName));
		//                        spGroup.AddUser(spUser);
		//                    }
		//                    web.Update();
		//                    web.AllowUnsafeUpdates = false;
		//                }
					
		//            }
		//        }
		//    }
		//}

		private void UpdateSharePointGroups(SharePoint.Data.User user, List<SharePoint.Data.Group> groups, bool IsAdd)
		{
			foreach (SharePoint.Data.Group g in groups)
			{
				foreach (SharePoint.Data.Site s in g.Sites)
				{
					
					//using (var site = new SPSite(new Guid("f7ac880b-717d-4315-86a7-70a46abf0c68")))
					using (var site = new SPSite(s.SiteCollection.SiteCollectionID))
					{
						
						
						if (site.AllWebs[s.SiteID] != null)
						{
							//using (var web = site.OpenWeb(new Guid("32f96c87-d844-429f-ab7b-03cb2ba85d6b")))
							using (var web = site.OpenWeb(s.SiteID))
							{
								web.AllowUnsafeUpdates = true;
								//SPUser spUser = web.EnsureUser(HttpContext.Current.User.Identity.Name);
								SPUser spUser = web.EnsureUser(String.Format("i:0#.w|{0}", user.UserName));
                                try
                                {
                                    var spGroup = web.Groups[g.Name];
                                    if (spGroup != null && spUser != null)
                                    {
                                        //SPUser spUser = web.EnsureUser(String.Format("i:0#.w|{0}", user.UserName));
                                        //SPUser spUser = web.EnsureUser(user.UserName);
                                        if (IsAdd)
                                            spGroup.AddUser(spUser);
                                        else
                                            spGroup.RemoveUser(spUser);
                                    }
                                    web.Update();
                                }
                                catch (Exception ex)
                                {
                                    throw new Exception("Group: " + g.Name + " Site: " + web.Url + " Message: " + ex.Message, ex);
                                }
								//web.AllowUnsafeUpdates = false;
							}
						}

					}
				}
			}
		}

		private void CleanUserAssociations(SharePoint.Data.User user)
		{
			if (user != null)
			{
				// Remove Role association
				string[] keys = this.RoleKeywords.Split(';');
                if (user.Groups != null)
                {
                    List<SharePoint.Data.Group> toDelete = new List<SharePoint.Data.Group>();
                    foreach (SharePoint.Data.Group g in user.Groups.ToList())
                    {
						if (keys.Any(k => !String.IsNullOrEmpty(k) && g.Name.Contains(k)) && g.Sites != null)
                        {
                            toDelete.Add(g);
                            //user.Groups.Remove(g);
                        }
                    }
                    user.Groups.Clear();

                    UpdateSharePointGroups(user, toDelete, false);

                    SlamCmsContext.Entities.SaveChanges();
                }
				// Remove Topic association
                if (user.Tags != null)
                {
                    user.Tags.Clear();
                    SlamCmsContext.Entities.SaveChanges();
                }

                // clean Cache
				SlamCmsContext.Data.Cache.InvalidateUsers();
				SlamCmsContext.Data.Cache.InvalidateCore();
				SlamCmsContext.Data.Cache.InvalidateTags();
			}
		
		}


		private List<SharePoint.Data.Group> GetGroups()
		{
			List<SharePoint.Data.Group> groups = new List<SharePoint.Data.Group>();

			if (!String.IsNullOrEmpty(this.hdnSelectedRoles.Value))
			{
				//string[] selectedRoles = this.hdnSelectedRoles.Value.Split(';');
                int[] selectedId = this.hdnSelectedRoles.Value.Split(';').Select(i => int.Parse(i)).ToArray();

				//List<string> searchGroups = new List<string>();

                //foreach (string s in selectedRoles)
                //{
                //    string[] arrayRole = s.Split(':');
                //    string groupName = arrayRole.Length < 3 ? (arrayRole.Length == 2 ? arrayRole[1] : s) : string.Empty;
                //    if (!searchGroups.Equals(groupName))
                //        searchGroups.Add(groupName);
                //}



                //string[] keywords = searchGroups.ToArray<string>();

                //groups = (from g in SlamCmsContext.Entities.Groups.ToList().Where(g => keywords.Any(k => g.Name.Contains(k)))
                //              select g).ToList();

                groups = SlamCmsContext.Entities.Groups.ToList().Where(g => selectedId.Contains(g.GroupID)).ToList();
			}

			return groups;
		}

		private List<SharePoint.Data.Tag> GetTopics()
		{
			List<SharePoint.Data.Tag> topics = new List<SharePoint.Data.Tag>();

			if (!String.IsNullOrEmpty(this.hdnSelectedTopics.Value))
			{
				string[] selectedId = this.hdnSelectedTopics.Value.Split(';');

				topics = SlamCmsContext.Entities.Tags.ToList().Where(t => selectedId.Contains(t.TagID)).ToList();
			}

			return topics;

			//var category = SlamCmsContext.Data.TagCategories.Where(cat => cat.Title.Equals("Topics")).FirstOrDefault();

			//var tagTree = SlamCmsContext.Data.GetTagTree().FilterTagCategories(new string[] { category.TagCategoryId });


			//var topics = tagTree.FindNodes(n => !String.IsNullOrEmpty(n.Identifier)).Select(t => t.Identifier).ToArray();

			//return topics
		}

	 

		//protected void btnDelete_Click(object sender, EventArgs e)
		//{
		//    var user = SlamCmsContext.Entities.Users.Include("Groups").ToList().Where(u => u.Name.ToUpper().Equals(this.hdnSelectedUser.Value.ToUpper()) ||
		//                                           u.UserName.ToUpper().Equals(this.hdnSelectedUser.Value.ToUpper())).FirstOrDefault();
		//    CleanUserAssociations(user);
		//}

	  

		//private List<Tag> GetOwnedTags()
		//{
		//    string[] selectedRoles = this.hdnSelectedRoles.Value.Split(';');

		
		//}

	   
	}

	public enum ControlMode
	{
		New,
		Edit
	}
}
